package com.ywu.data.source.standard.service;

import com.ywu.boot.context.YwuContextHolder;
import com.ywu.common.entity.PageList;
import com.ywu.common.gson.GsonUtils;
import com.ywu.common.page.PageService;
import com.ywu.common.result.CommonResult;
import com.ywu.common.utils.TimerIdGenerateUtil;
import com.ywu.data.source.standard.constant.YwuDataSourceConstant;
import com.ywu.data.source.standard.data.YwuDataSourceRepository;
import com.ywu.data.source.standard.data.YwuDataTableRepository;
import com.ywu.data.source.standard.dto.YwuDataTableDto;
import com.ywu.data.source.standard.dto.YwuDataTableFieldDto;
import com.ywu.data.source.standard.entity.YwuDataSourceEntity;
import com.ywu.data.source.standard.entity.YwuDataTableEntity;
import com.ywu.data.source.standard.source.YwuExecSqlCoreService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;

/**
 * @ClassName YwuDataTableService
 * @Description TODO
 * @Author GroundDemo
 * @Date 2024/10/27 18:48
 * @Version 1.0
 **/
@Service
public class YwuDataTableService {
    @Autowired
    private YwuDataTableRepository repository;

    @Autowired
    private YwuDataSourceRepository ywuDataSourceRepository;

    @Autowired
    private YwuExecSqlCoreService ywuExecSqlCoreService;

    /**
    * @Author GroundDemo
    * @Description 创建数据表
    * @Date 16:49 2024/10/28
    * @Param [ywuDataTableDto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    @Transactional
    public CommonResult<Object> createTable(YwuDataTableDto ywuDataTableDto) {
        // 查询当前数据表是否存在 -- 同一数据库下不能存在同名数据表
        YwuDataTableEntity search = new YwuDataTableEntity();
        search.setTableName(ywuDataTableDto.getTableName());
        search.setDataSourceCode(ywuDataTableDto.getDataSourceCode());
        YwuDataTableEntity queryRes = repository.getEntity(search);
        if (Objects.nonNull(queryRes)) {
            return CommonResult.error().setCode(YwuDataSourceConstant.TABLE_NAME_HAS_EXISTS_CODE)
                    .setErrorCode(YwuDataSourceConstant.TABLE_NAME_HAS_EXISTS_ERROR_CODE)
                    .setMessage(YwuDataSourceConstant.TABLE_NAME_HAS_EXISTS_ERROR_MESSAGE);
        }
        // 构建参数
        YwuDataTableEntity ywuDataTableEntity = new YwuDataTableEntity();
        BeanUtils.copyProperties(ywuDataTableDto, ywuDataTableEntity);
        // 为每个字段添加一个唯一ID
        ywuDataTableDto.getFieldInfo().forEach(res -> {
            res.setId(TimerIdGenerateUtil.nextId());
        });
        ywuDataTableEntity.setId(TimerIdGenerateUtil.nextId());
        ywuDataTableEntity.setTenantId(YwuContextHolder.getCurrentContext().getYwuContextTenant().getTenantId());
        ywuDataTableEntity.createInfo(YwuContextHolder.getCurrentContext().getYwuContextUser().getUserAccount());
        ywuDataTableEntity.setFieldInfoStr(GsonUtils.serialize(ywuDataTableDto.getFieldInfo()));
        // 根据code查询数据源相关信息
        YwuDataSourceEntity dataSourceSearch = new YwuDataSourceEntity();
        dataSourceSearch.setCode(ywuDataTableDto.getDataSourceCode());
        dataSourceSearch.setTenantId(YwuContextHolder.getCurrentContext().getYwuContextTenant().getTenantId());
        YwuDataSourceEntity dataSourceQueryRes = ywuDataSourceRepository.getEntity(dataSourceSearch);
        ywuDataTableEntity.setDataSourceType(dataSourceQueryRes.getDataSourceType());
        ywuDataTableEntity.setDataSourceCode(dataSourceQueryRes.getCode());
        ywuDataTableEntity.setDataSourceName(dataSourceQueryRes.getName());
        // 创建数据表
        ywuExecSqlCoreService.createTable(ywuDataTableEntity);
        // 插入数据库
        repository.insertDataTable(ywuDataTableEntity);
        return CommonResult.success(ywuDataTableEntity.getId());
    }

    /**
    * @Author GroundDemo
    * @Description 修改数据表信息
    * @Date 16:57 2024/10/28
    * @Param [ywuDataTableDto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    @Transactional
    public CommonResult<Object> updateTable(YwuDataTableDto ywuDataTableDto) {
        // 判断id是否存在
        YwuDataTableEntity search = new YwuDataTableEntity();
        search.setId(ywuDataTableDto.getId());
        search.setTenantId(YwuContextHolder.getCurrentContext().getYwuContextTenant().getTenantId());
        YwuDataTableEntity queryRes = repository.getEntity(search);
        if (Objects.isNull(queryRes)) {
            return CommonResult.error().setCode(YwuDataSourceConstant.RESOURCE_IS_NOT_EXISTS_CODE)
                    .setMessage(YwuDataSourceConstant.RESOURCE_IS_NOT_EXISTS_ERROR_MESSAGE)
                    .setErrorCode(YwuDataSourceConstant.RESOURCE_IS_NOT_EXISTS_ERROR_CODE);
        }
        if (!queryRes.getTableName().equals(ywuDataTableDto.getTableName())) {
            // 判断数据表名是否已存在
            search.setId(null);
            search.setTenantId(null);
            search.setTableName(ywuDataTableDto.getTableName());
            search.setDataSourceCode(ywuDataTableDto.getDataSourceCode());
            YwuDataTableEntity queryRes2 = repository.getEntity(search);
            if (Objects.nonNull(queryRes2)) {
                return CommonResult.error().setCode(YwuDataSourceConstant.TABLE_NAME_HAS_EXISTS_CODE)
                        .setMessage(YwuDataSourceConstant.TABLE_NAME_HAS_EXISTS_ERROR_MESSAGE)
                        .setErrorCode(YwuDataSourceConstant.TABLE_NAME_HAS_EXISTS_ERROR_CODE);
            }
        }
        // 构建参数
        YwuDataTableEntity ywuDataTableEntity = new YwuDataTableEntity();
        BeanUtils.copyProperties(ywuDataTableDto, ywuDataTableEntity);
        ywuDataTableEntity.setTenantId(YwuContextHolder.getCurrentContext().getYwuContextTenant().getTenantId());
        ywuDataTableEntity.updateInfo(YwuContextHolder.getCurrentContext().getYwuContextUser().getUserAccount());
        ywuDataTableEntity.setDataSourceName(queryRes.getDataSourceName());
        ywuDataTableEntity.setDataSourceType(queryRes.getDataSourceType());
        ywuDataTableEntity.setDataSourceCode(queryRes.getDataSourceCode());
        // 对于没有id值的数据设置ID值
        List<YwuDataTableFieldDto> fieldInfo = ywuDataTableEntity.getFieldInfo();
        fieldInfo.forEach(res -> {
            if (StringUtils.isEmpty(res.getId())) {
                res.setId(TimerIdGenerateUtil.nextId());
            }
        });
        ywuDataTableEntity.setFieldInfoStr(GsonUtils.serialize(fieldInfo));
        queryRes.setFieldInfo(GsonUtils.deserializeList(queryRes.getFieldInfoStr(), YwuDataTableFieldDto.class));
        // 修改数据表
        ywuExecSqlCoreService.updateTable(queryRes, ywuDataTableEntity);
        // 修改数据库中的数据
        repository.updateTable(ywuDataTableEntity);
        return CommonResult.success(null);
    }

    /**
    * @Author GroundDemo
    * @Description 删除数据表
    * @Date 16:58 2024/10/28
    * @Param [ywuDataTableDto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> deleteTable(YwuDataTableDto ywuDataTableDto) {
        // 查询数据是否存在
        YwuDataTableEntity search = new YwuDataTableEntity();
        search.setId(ywuDataTableDto.getId());
        search.setTenantId(YwuContextHolder.getCurrentContext().getYwuContextTenant().getTenantId());
        YwuDataTableEntity queryRes = repository.getEntity(search);
        if (Objects.isNull(queryRes)) {
            return CommonResult.error().setCode(YwuDataSourceConstant.RESOURCE_IS_NOT_EXISTS_CODE)
                    .setErrorCode(YwuDataSourceConstant.RESOURCE_IS_NOT_EXISTS_ERROR_CODE)
                    .setMessage(YwuDataSourceConstant.RESOURCE_IS_NOT_EXISTS_ERROR_MESSAGE);
        }
        // 构建参数
        YwuDataTableEntity ywuDataTableEntity = new YwuDataTableEntity();
        BeanUtils.copyProperties(queryRes, ywuDataTableEntity);
        ywuDataTableEntity.setTenantId(YwuContextHolder.getCurrentContext().getYwuContextTenant().getTenantId());
        // 删除数据表
        ywuExecSqlCoreService.deleteTable(ywuDataTableEntity);
        // 删除数据库中的数据
        repository.deleteTable(ywuDataTableEntity);
        return CommonResult.success(null);
    }

    /**
    * @Author GroundDemo
    * @Description 分页查询数据表数据
    * @Date 17:01 2024/10/28
    * @Param [ywuDataTableDto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> queryTablePageList(YwuDataTableDto ywuDataTableDto) {
        ywuDataTableDto.setTenantId(YwuContextHolder.getCurrentContext().getYwuContextTenant().getTenantId());
        // 查询数量
        int count = repository.queryCount(ywuDataTableDto);
        // 构建分页参数
        PageService.execPageStartAndEnd(ywuDataTableDto.getPageInfo());
        // 查询分页数据
        List<YwuDataTableEntity> pageList = repository.queryPageList(ywuDataTableDto);
        // 构建fieldInfo
        pageList.forEach(res -> {
            List<YwuDataTableFieldDto> fieldDto = GsonUtils.deserializeList(res.getFieldInfoStr(), YwuDataTableFieldDto.class);
            res.setFieldInfo(fieldDto);
        });
        PageList<YwuDataTableEntity> res = new PageList<>(ywuDataTableDto.getPageInfo().getPageIndex(), ywuDataTableDto.getPageInfo().getPageSize(),
                count, pageList);
        return CommonResult.success(res);
    }

    /**
    * @Author GroundDemo
    * @Description 查询数据表下的所有字段
    * @Date 13:43 2024/10/31
    * @Param [ywuDataTableDto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> queryFieldsByTable(YwuDataTableDto ywuDataTableDto) {
        // 查询数据
        YwuDataTableEntity search = new YwuDataTableEntity();
        search.setTenantId(YwuContextHolder.getCurrentContext().getYwuContextTenant().getTenantId());
        search.setId(ywuDataTableDto.getId());
        search.setCode(ywuDataTableDto.getCode());
        YwuDataTableEntity queryRes = repository.getEntity(search);
        if (Objects.isNull(queryRes)) {
            return CommonResult.error().setCode(YwuDataSourceConstant.RESOURCE_IS_NOT_EXISTS_CODE)
                    .setMessage(YwuDataSourceConstant.RESOURCE_IS_NOT_EXISTS_ERROR_MESSAGE)
                    .setErrorCode(YwuDataSourceConstant.RESOURCE_IS_NOT_EXISTS_ERROR_CODE);
        }
        queryRes.setFieldInfo(GsonUtils.deserializeList(queryRes.getFieldInfoStr(), YwuDataTableFieldDto.class));
        return CommonResult.success(queryRes.getFieldInfo());
    }
}
